/**
 * 用户模型。
 */
const constants = require('../../utils/constants');
const models = require('../../utils/models');

module.exports = class User extends think.Model {
    get relation() {
        return {
            openid: {
                type: think.Model.HAS_MANY,
                model: models.UserOpenid,
                fKey: 'userId'
            }
        };
    }

    /**
     * 获取用户列表。
     */
    async getAll(nickName, appid, page, size) {
        const filter = {};
        if(nickName) filter.nickName = new RegExp(`.*${nickName}.*`);
        if(appid) filter.appid = appid;

        return this.where(filter).page(page, size).select();
    }

    /**
     * 创建用户.
     *
     * @param userData
     */
    async create(userData){
        let user = await this.getByOpenid(userData.openid);

        // 用户未注册，新建一个用户，未授权用户使用默认昵称与头像
        if(think.isEmpty(user)){
            // 如果不存在，用unionid再判断一次
            if(!think.isEmpty(userData.unionid) && !think.isEmpty(userData.unionid)) {
                user = await this.getByUnionid(userData.unionid);
            }

            // 真的不存在
            if(think.isEmpty(user)) {
                if (think.isEmpty(userData.nickName)) {
                    userData.nickName = '脸脸看用户';
                }

                if (think.isEmpty(userData.avatarUrl)) {
                    userData.avatarUrl = think.config('user.defaultAvatar');
                }

                // 保存用户信息
                user = {
                    unionid: userData.unionid || "",
                    nickName: userData.nickName,
                    avatarUrl: userData.avatarUrl,
                    gender: userData.gender || 0,
                    country: userData.country || "",
                    province: userData.province || "",
                    city: userData.city || '',
                    regTime: new Date()
                };
                user.id = await this.add(user);
                user.openid = userData.openid;
            }

            // 保存关联openid
            let openidModel = think.model(models.UserOpenid);
            await openidModel.add({
                userId: user.id,
                openid: userData.openid,
                appid: userData.appid,
                regTime: new Date()
            });
        }

        return user;
    }

    /**
     * 获取一个。
     */
    async getByUserId(id) {
        const pk = this.pk;
        return this.field('id, nickName, avatarUrl, gender, channelId').where({[pk]: id}).find();
    }

    /**
     * 根据unionid获取用户信息.
     */
    async getByUnionid(unionid) {
        return this.where({unionid: unionid}).find();
    }

    /**
     * 根据openid获取用户信息。若用户不存在，仅返回当前的openid.
     */
    async getByOpenid(openid) {
        let openidModel = think.model(models.UserOpenid);
        let openidData = await openidModel.getOne(openid);
        if(think.isEmpty(openidData)) return null;

        return this.getByUserId(openidData.userId);
    }

    /**
     * 判断用户是否为开发者。
     *
     * @param id 用户ID
     */
    async isDeveloper(id) {
        const user = await this.where({id: id}).find();
        return user.role === 99;
    }

    /**
     * 判断用户是否被举报。
     */
    async isUserReported(userId) {
        const userCount = await this.where({id: userId, status: constants.UserStatus.Reported}).count();
        return userCount === 1;
    }

    /**
     * 设置为被举报状态。
     */
    async setReported(userId) {
        return this.where({id: userId}).update({
            status: constants.UserStatus.Reported
        });
    }

    /**
     * 获取用户所属的渠道。
     */
    async getChannel(userId) {
        const channels = await this.query('select c.* ' +
            'from channel c left join user u on c.userId = u.channelId ' +
            'where u.id = ' + userId + ' and c.status = ' + constants.ChannelStatus.Accepted);
        return think.isEmpty(channels) ? null : channels[0];
    }

    /**
     * 通过授权的code，请求微信服务器获取微信openid。
     *
     * @param appid
     * @param code
     */
    async getOpenidByAuthorizationCode(appid, code){
        const appModel = think.model(models.VendorTencentWechatApp);
        const secret = await appModel.getAppSecret(appid);
        if(think.isEmpty(secret)){
            throw new Error('无效appid。');
        }

        const maApi = think.model(models.VendorTencentMaApi);
        return maApi.getOpenid(appid, secret, code);
    }

    /**
     * 设置用户渠道。如果已经存在渠道，则不更新。
     *
     * @param userId
     * @param channelId
     * @param shareId
     */
    async setChannel(userId, channelId, shareId) {
        if (!think.isEmpty(shareId)) { // 有分享ID
            // 先判断分享者是不是渠道，如果是渠道ID计算完成；
            // 如果分享者不是渠道，则获取分享者的渠道，新用户与分享者为同一渠道
            const shareModel = think.model(models.Share);
            const shareCreatorId = await shareModel.getShareCreatorId(shareId);
            if (!think.isEmpty(shareCreatorId)) {
                const channelModel = think.model(models.Channel);
                channelId = await channelModel.getUserChannelId(shareCreatorId);
                if (think.isEmpty(channelId)) {
                    const channelUser = await this.field('channelId').where({id: shareCreatorId}).find();
                    channelId = channelUser.channelId
                }
            }
        }

        // 渠道仍然为空，设置为系统第一个渠道ID
        if (think.isEmpty(channelId)) {
            channelId = 1;
        }

        return this.where({
            id: userId,
            channelId: ['EXP', 'IS NULL']
        }).update({
            channelId: channelId
        });
    }
};
